package com.bajiao.service.config.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ijpay.alipay.AliPayApiConfig;
import com.ijpay.alipay.AliPayApiConfigKit;
import com.ijpay.wxpay.WxPayApiConfig;
import com.bajiao.common.constant.CacheConstant;
import com.bajiao.common.exception.DataHandleException;
import com.bajiao.entity.config.Config;
import com.bajiao.mapper.config.ConfigMapper;
import com.bajiao.service.config.ConfigService;
import com.bajiao.third.config.AliPayConfig;
import com.bajiao.third.config.WxPayConfig;
import com.bajiao.vo.config.ConfigVO;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: 系统配置
 * @Author: FanJq
 * @Date: 2024-10-1006-02
 * @Version: V1.0
 */
@Service
public class ConfigServiceImpl extends ServiceImpl<ConfigMapper, Config> implements ConfigService {

    @Autowired
    private WxPayConfig wxPayConfig;

    private static final Map<String, WxPayApiConfig> WX_CFG_MAP = new ConcurrentHashMap();

    @Autowired
    @Lazy
    private AliPayConfig alipayConfig;

    /**
     * @param configName
     * @description: 根据配置Name查询实体对象
     * @author: FanJq
     * @date: 2024-10-10/6/3
     * @return: java.util.List<com.bajiao.entity.config.Config>
     */
    @Override
    public List<Config> queryConfigByConfigName(String configName) {
        return baseMapper.queryConfigByConfigName(configName);
    }


    /**
     * @param configGroup
     * @param configValue
     * @description: 根据分组和Value查询标题
     * @author: FanJq
     * @date: 2024-10-10/6/3
     * @return: java.lang.String
     */
    @Override
    public String queryTitleByGroupAndValue(String configGroup, String configValue) {
        return baseMapper.queryTitleByGroupAndValue(configGroup, configValue);
    }

    /**
     * @param configGroup
     * @description: 根据分组查询Value值
     * @author: FanJq
     * @date: 2024-10-10/6/3
     * @return: java.lang.String
     */
    @Override
    public String queryValueByGroup(String configGroup) {
        return baseMapper.queryValueByGroup(configGroup);
    }

    /**
     * @param configGroup
     * @description: 根据分组查询Name和Value
     * @author: FanJq
     * @date: 2024-10-10
     * @return: java.util.List<java.util.Map>
     */
    @Override
    @Cacheable(value = CacheConstant.CONFIG_GROUP, key = "#configGroup")
    public Map queryNameAndValueByGroup(String configGroup) {
        Map map = new HashMap<>();
        //表中查询配置信息
        List<ConfigVO> configVOList = baseMapper.queryNameAndValueByGroup(configGroup);
        if (CollectionUtils.isNotEmpty(configVOList)) {
            for (ConfigVO configVO : configVOList) {
                map.put(configVO.getConfigName(), configVO.getConfigValue());
            }
        }
        return map;
    }

    @Override
    @Cacheable(value = CacheConstant.CONFIG, key = "#configGroup+#configName", unless = "#result == null")
    public String getValue(String configGroup, String configName) {
        QueryWrapper<Config> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Config::getConfigGroup, configGroup).eq(Config::getConfigName, configName);
        Config config = baseMapper.selectOne(queryWrapper);
        if (config == null) {
            return "";
        }
        return String.valueOf(config.getConfigValue());
    }

    @Caching(evict = {
            @CacheEvict(value = CacheConstant.CONFIG, key = "#configGroup+#configName", beforeInvocation = true),
            @CacheEvict(value = CacheConstant.CONFIG_GROUP, key = "#configGroup", beforeInvocation = true),
            @CacheEvict(value = CacheConstant.CONFIG_NAME, key = "#configName", beforeInvocation = true),
    })
    @Override
    public void updateByConfigGroupAndConfigName(String configGroup, String configName, String value, String title) {
        LambdaUpdateWrapper<Config> lambdaQueryWrapper = new LambdaUpdateWrapper();
        lambdaQueryWrapper
                .eq(Config::getConfigGroup, configGroup)
                .eq(Config::getConfigName, configName);

        if (ObjectUtil.isEmpty(this.getOne(lambdaQueryWrapper))) {
            Config config = new Config().setConfigGroup(configGroup).setConfigName(configName).setConfigValue(value)
                    .setDescription(title).setTitle(title).setCreateTime(new Date()).setCreateBy("admin");
            baseMapper.insert(config);
        } else {
            Config systemConfig = new Config();
            systemConfig.setConfigValue(value);
            baseMapper.update(systemConfig, lambdaQueryWrapper);
        }
    }

    /**
     * 获取支付宝支付配置
     * （更改配置后调用改方法获取老的老的存在的话删除 AliPayApiConfigKit.removeApiConfig(config)）
     *
     * @return
     */
    @Override
    public AliPayApiConfig getAliPayApiConfig() {
        Map map = queryNameAndValueByGroup("aliPay");
        String appId = (String) map.get("appId");
        String privateKey = (String) map.get("privateKey");//应用私钥
        String publicKey = (String) map.get("publicKey");//支付宝公钥

        /**
         * 下面采用普通模式，如果采用证书模式还需设置下方数据
         *  .setAppCertPath(应用公钥证书)
         *  .setAliPayCertPath(支付宝公钥证书)
         *  .setAliPayRootCertPath(支付宝根证书)
         */
        AliPayApiConfig aliPayApiConfig = AliPayApiConfig.builder()
                .setAppId(appId)
                .setAliPayPublicKey(publicKey)
                .setPrivateKey(privateKey)
                .setCharset(alipayConfig.charset)
                .setServiceUrl(alipayConfig.url)
                .setSignType(alipayConfig.singType)
                // 普通公钥方式
                .build();
        // 证书模式
        //.buildByCert();


        if (aliPayApiConfig == null) {
            throw new DataHandleException("未获取到支付相关配置!");
        }

        AliPayApiConfigKit.setThreadLocalAppId(aliPayApiConfig.getAppId());// 2.1.2 之后的版本，可以不用单独设置
        AliPayApiConfigKit.setThreadLocalAliPayApiConfig(aliPayApiConfig);
        return aliPayApiConfig;
    }

    /**
     * @Description
     * 获取微信支付配置bean
     * @date 2024/12/19 9:48
     * @author FanJq
     * @param configGroup
     * @return {@link WxPayApiConfig}
    */
    @Override
    public WxPayApiConfig getWxPayApiConfig(String configGroup) {
        Map appMap = queryNameAndValueByGroup(configGroup);
        String appId = (String) appMap.get("appId");//appId
        String appSecret = (String) appMap.get("appSecret");//私钥

        Map wxPayMap = queryNameAndValueByGroup("wxPay");
        String partnerKey = (String) wxPayMap.get("partnerKey");//支付私钥
        String mchId = (String) wxPayMap.get("mchId");//商户号
        String certPath = wxPayMap.get("certPath").toString();
        if(System.getProperty("os.name").contains("Windows")){
            certPath = "D:" + certPath;
        }
        WxPayApiConfig apiConfig = WxPayApiConfig.builder()
                .appId(appId)
                .mchId(mchId)
                .partnerKey(partnerKey)
                .certPath(certPath + "apiclient_cert.p12")
                .certPemPath(certPath + "apiclient_cert.pem")
                .keyPemPath(certPath + "apiclient_key.pem")
                .domain("127.0.0.1")
                .build();

        if (apiConfig == null) {
            throw new DataHandleException("未获取到支付相关配置");
        }
        return apiConfig;
    }

    @Override
    public List<ConfigVO> queryConfigList(String configGroup) {
        return baseMapper.queryConfigList(configGroup);
    }

    @Override
    public ConfigVO queryConfig(String configGroup, String configName) {
        return baseMapper.queryConfig(configGroup, configName);
    }

    @Override
    @Cacheable(value = CacheConstant.CONFIG_NAME, key = "#configName")
    public String queryByConfigName(String configName) {
        Config config = baseMapper.selectOne(Wrappers.<Config>lambdaQuery().eq(Config::getConfigName, configName));
        if (config == null) {
            return "";
        }
        return String.valueOf(config.getConfigValue());
    }

    @Override
    public Map<String, String> getWxMiniConfig() {
        Map wxMiniApp = this.queryNameAndValueByGroup("wxMiniApp");
        return wxMiniApp;
    }

    /**
     * @Description
     * 获取回调路径
     * @date 2024/12/25 11:08
     * @author FanJq
     * @param name
     * @return {@link String}
    */
    @Override
    public String getCallback(String name) {
        String value = this.getValue("callback", name);
        return value;
    }
}
